package com.tang.websocket.v1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.convert.TypeDescriptor;

import java.nio.ByteBuffer;

/**
 * @author Tang
 * @classname EncoderDecoderSupport
 * @description [ EncoderDecoderSupport ]
 * @date 2022/11/28 17:27
 */
public abstract class EncoderDecoderSupport<T,R> {

    private ConverterRegistry converterRegistry;

    @Autowired
    public void setConverterRegistry(ConverterRegistry converterRegistry) {
        this.converterRegistry = converterRegistry;
    }

    public R encode(T object){
        Class<?> type = getType().getType();
        Class<?> messageType = getMessageType().getType();
        Converter<T,R> converter = converterRegistry.selectConverter(type, messageType);
        if (converter != null) {
            return converter.convert(object);
        }
        return null;
    }

    public T decode(R object){
        Class<?> messageType = getType().getType();
        Class<?> type = getMessageType().getType();
        Converter<R,T> converter = converterRegistry.selectConverter(type, messageType);
        if (converter != null) {
            return converter.convert(object);
        }
        return null;
    }

    public static class TextEncoder<R> extends EncoderDecoderSupport<String, R> {
    }

    public static class TextDecoder<T> extends EncoderDecoderSupport<T, String> {
    }

    public static class BinaryEncoder<R> extends EncoderDecoderSupport<ByteBuffer, R> {
    }

    public static class BinaryDecoder<T> extends EncoderDecoderSupport<T, ByteBuffer> {
    }

    protected TypeDescriptor getType(){
        return TypeDescriptor.valueOf(resolveTypeArguments()[0]);
    }

    protected TypeDescriptor getMessageType(){
        return TypeDescriptor.valueOf(resolveTypeArguments()[1]);
    }

    private Class<?>[] resolveTypeArguments() {
        return GenericTypeResolver.resolveTypeArguments(getClass(), EncoderDecoderSupport.class);
    }

}
